package com.qn.visitor.util;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.qn.core.resources.ResourcesCore;
import com.qn.core.resources.ResourcesHeader;
import com.qn.visitor.model.UserVisitorRequest;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.*;
/**
 * qingniu-cloud user source analysis
 *
 * @Author: TXG
 * @Date: 2024/6/11
 * @Version V0.0.2
 */
public class VisitorUtil {
    private static final String SEPARATOR=",";
    private static final String IPV4_DEFAULT = "127.0.0.1";
    private static final String IPV6_DEFAULT = "0:0:0:0:0:0:0:1";
    /**
     * 获取访客信息
     *
     * @param request 请求信息
     * @param tz      访客时区
     * @return 访客对象
     */
    public static UserVisitorRequest getVisitor(HttpServletRequest request,
                                                Integer did,
                                                String vu,
                                                String ru,
                                                String tz) throws MalformedURLException {
        UserVisitorRequest visitorModel = new UserVisitorRequest();
        //访客来路
        visitorModel.setReferer(ru);
        //访问网址
        visitorModel.setUrl(vu);
        visitorModel.setDId(did);
        visitorModel.setClientIp(getIp(request));
        //语言
        visitorModel.setClientLanguage(getLanguage(request));
        //访客代理
        visitorModel.setUserAgent(getUserAgent(request));
        //域名
        visitorModel.setHost(getHost(visitorModel.getUrl()));
        visitorModel.setCkf(getVisitorId(request));
        //访客指纹
        visitorModel.setJa4(getJa4(request));
        visitorModel.setH2(getH2(request));
        //访客时区
        visitorModel.setTimeZone(tz);
        visitorModel.setPath(new URL(vu).getPath());
        //判断访客指纹
        if (StringUtils.isBlank(visitorModel.getCkf())) {
            visitorModel.setCkf(UUID.randomUUID().toString());
        }

        return visitorModel;
    }

    public static UserVisitorRequest getVisitorEvent(HttpServletRequest request) throws MalformedURLException {
        UserVisitorRequest visitorModel = new UserVisitorRequest();
        //访客来路
        visitorModel.setReferer(getReferer(request));
        //访问网址
        visitorModel.setUrl(visitorModel.getReferer());
        visitorModel.setClientIp(getIp(request));
        visitorModel.setHost(getHost(visitorModel.getUrl()));
        visitorModel.setCkf(getVisitorId(request));
        visitorModel.setJa4(getJa4(request));
        visitorModel.setH2(getH2(request));
        //visitorModel.setTimeZone(tz);//访客时区
        if (!StringUtils.isBlank(visitorModel.getUrl())) {
            visitorModel.setPath(new URL(visitorModel.getUrl()).getPath());
        }

        return visitorModel;
    }

    
    public static String getJa4(HttpServletRequest request) {
        if (request != null) {
            return request.getHeader(ResourcesHeader.X_JA4_FINGERPRINT);
        }
        return "";
    }


    public static String getH2(HttpServletRequest request) {
        if (request != null) {
            return request.getHeader(ResourcesHeader.X_HTTP2_FINGERPRINT);
        }
        return "";
    }

    /**
     * 获取当前网络ip
     */
    public static String getHost(String urlString) {
        try {
            URL url = new URL(urlString);
            return url.getHost();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取当前网络ip
     */
    
    public static String getIp(HttpServletRequest request) {
        String ipAddress = request.getHeader(ResourcesHeader.X_FORWARDED_FOR);
        if (StringUtils.isBlank(ipAddress) || ResourcesCore.UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader(ResourcesHeader.PROXY_CLIENT_IP);
        }
        if (StringUtils.isBlank(ipAddress) || ResourcesCore.UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader(ResourcesHeader.WL_PROXY_CLIENT_IP);
        }
        if (StringUtils.isBlank(ipAddress) || ResourcesCore.UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader(ResourcesHeader.X_REAL_IP);
        }
        if (StringUtils.isBlank(ipAddress) || ResourcesCore.UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (StringUtils.equals(ipAddress.toLowerCase(Locale.ROOT), IPV4_DEFAULT) ||
                    StringUtils.equals(ipAddress.toLowerCase(Locale.ROOT), IPV6_DEFAULT.toLowerCase(Locale.ROOT))) {
                InetAddress inet;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    System.err.println("获取IP失败：" + e.getMessage());
                    return IPV4_DEFAULT;
                }
                ipAddress = inet.getHostAddress();
            }
        }
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (StringUtils.isNotBlank(ipAddress)) {
            if (ipAddress.indexOf(SEPARATOR) > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(SEPARATOR));
            }
        }
        return ipAddress;
    }


    /**
     * 获取接受的语言
     */
    public static String getLanguage(HttpServletRequest request) {
        if (request != null) {
            return request.getHeader(ResourcesHeader.ACCEPT_LANGUAGE);
        }
        return "";
    }

    /**
     * 获取来路
     */
    public static String getReferer(HttpServletRequest request) {
        if (request != null) {
            return request.getHeader(ResourcesHeader.REFERER);
        }
        return "";
    }

    public static String getUserAgents(HttpServletRequest request) {
        if (request != null) {
            return request.getHeader(ResourcesHeader.USER_AGENT);
        }
        return "";
    }

    public static Map<String, String> getUserAgent(HttpServletRequest request) {
        Map<String, String> requestHeaders = new HashMap<>(11);
        requestHeaders.put(ResourcesHeader.USER_AGENT, request.getHeader(ResourcesHeader.USER_AGENT));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA, request.getHeader(ResourcesHeader.SEC_CH_UA));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_ARCH, request.getHeader(ResourcesHeader.SEC_CH_UA_ARCH));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_BITNESS, request.getHeader(ResourcesHeader.SEC_CH_UA_BITNESS));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_FULL_VERSION, request.getHeader(ResourcesHeader.SEC_CH_UA_FULL_VERSION));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_FULL_VERSION_LIST, request.getHeader(ResourcesHeader.SEC_CH_UA_FULL_VERSION_LIST));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_MOBILE, request.getHeader(ResourcesHeader.SEC_CH_UA_MOBILE));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_MODEL, request.getHeader(ResourcesHeader.SEC_CH_UA_MODEL));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_PLATFORM, request.getHeader(ResourcesHeader.SEC_CH_UA_PLATFORM));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_PLATFORM_VERSION, request.getHeader(ResourcesHeader.SEC_CH_UA_PLATFORM_VERSION));
        requestHeaders.put(ResourcesHeader.SEC_CH_UA_WOW64, request.getHeader(ResourcesHeader.SEC_CH_UA_WOW64));
        return requestHeaders;
    }

    /**
     * 获取访问链接
     */
    public static String getVisitUrl(HttpServletRequest request) {
        if (request != null) {
            return request.getRequestURL().toString() + (StringUtils.isNotBlank(request.getQueryString()) ? "?" + request.getQueryString() : "");
        }
        return "";
    }

    public static String getVisitorId(HttpServletRequest request) {
        if (request != null) {
            Cookie[] cks = request.getCookies();
            if (cks == null || cks.length < 1) {
                return null;
            }
            for (Cookie ck : cks) {
                if ("vid".equals(ck.getName())) {
                    return ck.getValue();
                }
            }
        }
        return "";
    }
}
